#pragma once


template <class T>
class RefPtr
{
public:
    // construction and destruction
    RefPtr (T* obj = 0);
    RefPtr (const RefPtr& pointer);
    ~RefPtr ();

    // implicit conversions
	operator T* () const;
    T& operator* () const;
    T* operator-> () const;

	// assignment
    RefPtr& operator= (T* obj);
    RefPtr& operator= (const RefPtr& ref);

    // comparisons
    bool operator== (T* obj) const;
    bool operator!= (T* obj) const;
    bool operator== (const RefPtr& ref) const;
    bool operator!= (const RefPtr& ref) const;

protected:
    // the shared object
    T* mRefObj;
};



#define P( cls) RefPtr< cls >

//----------------------------------------------------------------------------
template <class T>
RefPtr<T>::RefPtr (T* obj)
{
    mRefObj = obj;
    if (mRefObj)
    {
        mRefObj->IncRef();
    }
}
//----------------------------------------------------------------------------
template <class T>
RefPtr<T>::RefPtr (const RefPtr& pointer)
{
    mRefObj = pointer.mRefObj;
    if (mRefObj)
    {
        mRefObj->IncRef();
    }
}
//----------------------------------------------------------------------------
template <class T>
RefPtr<T>::~RefPtr ()
{
    if (mRefObj)
    {
        mRefObj->DecRef();
    }
}
//----------------------------------------------------------------------------
template <class T>
RefPtr<T>::operator T* () const
{
    return mRefObj;
}

//----------------------------------------------------------------------------
template <class T>
T& RefPtr<T>::operator* () const
{
    return *mRefObj;
}
//----------------------------------------------------------------------------
template <class T>
T* RefPtr<T>::operator-> () const
{
    return mRefObj;
}
//----------------------------------------------------------------------------
template <class T>
RefPtr<T>& RefPtr<T>::operator= (T* obj)
{
    if (mRefObj != obj)
    {
        if (obj)
        {
            obj->IncRef();
        }

        if (mRefObj)
        {
            mRefObj->DecRef();
        }

        mRefObj = obj;
    }
    return *this;
}
//----------------------------------------------------------------------------
template <class T>
RefPtr<T>& RefPtr<T>::operator= (const RefPtr& pointer)
{
    if (mRefObj != pointer.mRefObj)
    {
        if (pointer.mRefObj)
        {
            pointer.mRefObj->IncRef();
        }

        if (mRefObj)
        {
            mRefObj->DecRef();
        }

        mRefObj = pointer.mRefObj;
    }
    return *this;
}
//----------------------------------------------------------------------------
template <class T>
bool RefPtr<T>::operator== (T* obj) const
{
    return mRefObj == obj;
}
//----------------------------------------------------------------------------
template <class T>
bool RefPtr<T>::operator!= (T* obj) const
{
    return mRefObj != obj;
}
//----------------------------------------------------------------------------
template <class T>
bool RefPtr<T>::operator== (const RefPtr& pointer) const
{
    return mRefObj == pointer.mRefObj;
}
//----------------------------------------------------------------------------
template <class T>
bool RefPtr<T>::operator!= (const RefPtr& pointer) const
{
    return mRefObj != pointer.mRefObj;
}